/*
 * Copyright (c) 2003-2010, Live Media Pty. Ltd.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted
 * provided that the following conditions are met:
 *
 *  1. Redistributions of source code must retain the above copyright notice, this list of
 *     conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright notice, this list of
 *     conditions and the following disclaimer in the documentation and/or other materials
 *     provided with the distribution.
 *  3. Neither the name of Live Media nor the names of its contributors may be used to endorse
 *     or promote products derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package com.argot.mcg;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.nio.channels.FileChannel;
import java.util.Iterator;

import com.argot.ReferenceTypeMap;
import com.argot.TypeException;
import com.argot.TypeLibrary;
import com.argot.TypeLocation;
import com.argot.TypeLocationBase;
import com.argot.TypeLocationDefinition;
import com.argot.TypeLocationName;
import com.argot.TypeLocationRelation;

public class ArgotHeaderGenerator
{
	
	TypeLibrary _library;
	ReferenceTypeMap _map;
	
	public ArgotHeaderGenerator(TypeLibrary library, ReferenceTypeMap map)
	{
		_library = library;
		_map = map;
	}

	public void generateOutput(FileOutputStream header) 
	throws IOException, TypeException
	{
		ClassLoader cl = this.getClass().getClassLoader();
		InputStream in = cl.getResourceAsStream( "data/header.txt" );
		
		
		//FileChannel in = new FileInputStream("data/header.txt").getChannel();
		//FileChannel out = header.getChannel();

		PrintWriter writer = new PrintWriter( header );
		
		
		writer.write("/* Generated output */\n");
		writer.write("/* Argot MCG (Micro Code Generator) Version "+ ArgotMicroCodeGenerator.VERSION +" */\n");
		writer.write("\n");
		writer.write("#ifndef DICTIONARY_H_\n");
		writer.write("#define DICTIONARY_H_\n\n");

		Iterator i = _map.getIdList().iterator();
		
		while(i.hasNext())
		{
			int id = ((Integer) i.next()).intValue();
			
			String name="";
			TypeLocation location = _map.getLocation(id);
			if (location instanceof TypeLocationDefinition)
			{
				TypeLocationDefinition locDef = (TypeLocationDefinition) location;
				name = locDef.getName().getFullName();
			}
			else if (location instanceof TypeLocationName)
			{
				TypeLocationName locName = (TypeLocationName) location;
				name = locName.getName().getFullName();
			}
			else if (location instanceof TypeLocationBase)
			{
				TypeLocationBase locBase = (TypeLocationBase) location;
				name = "__BASE__";
			}
			else if (location instanceof TypeLocationRelation)
			{
				TypeLocationRelation locRelation = (TypeLocationRelation) location;
				name = _map.getLibrary().getName(locRelation.getId()).getFullName();
				name += "#" + locRelation.getTag();
			}
			
			if (!"".equals(name))
			{
				//String name = _map.getName(id).getFullName();
				name = name.replaceAll("\\.","_");
				name = name.replaceAll("#","_");
				name = name.toUpperCase();
			}
			writer.write( "#define " + name + " " + id + "\n");
		}
		
		writer.write("\n\n");
		writer.flush();
		
		// JavaVM does its best to do this as native I/O operations.
		//in.transferTo (0, 10000, out);
		byte buffer[] = new byte[1024];
		int read = -1;
		while ((read = in.read(buffer))  > -1)
		{
			header.write(buffer,0,read);
		}

		writer.write("\n\n#endif /*DICTIONARY_H_*/\n\n");
		writer.flush();
		
		// Closing file channels will close corresponding stream objects as well.
		header.close();
		in.close();		
	}

}
